package com.lcm.weam.service.algo.impl;

import Jama.Matrix;
import com.lcm.weam.dao.algo.GmMapper;
import com.lcm.weam.dao.algo.MarkovMapper;
import com.lcm.weam.entity.algo.*;
import com.lcm.weam.service.algo.PredictService;
import com.lcm.weam.util.BaseTypeUtil;
import com.lcm.weam.util.ExcelHandler;
import com.lcm.weam.util.GMUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Service
public class PredictServiceImpl implements PredictService {

    @Autowired
    private GmMapper gmMapper;

    @Autowired
    private MarkovMapper markovMapper;

    //输入流是excel文件
    @Override
    public GMResult GM(MultipartFile file, int t) throws IOException {
        double[] data = ExcelHandler.readGMData(file);
        String[] verify = GMUtil.verify(data); //级比验证结果
        double[] res = GMUtil.doAlgo(data, t); //GM结果
        double[] relativeError = GMUtil.relativeError(data, res); //相对误差结果
        double correlationDegree = GMUtil.correlationDegree(data, res); //均方差比值结果
        double cvalue = GMUtil.smallErrorProbability(data, res); //后验差比值
        //返回数据
        Double[] arr1 = BaseTypeUtil.doubleArrToDoubleArr(data);
        Double[] res1 = BaseTypeUtil.doubleArrToDoubleArr(res);
        Double[] relativeError1 = BaseTypeUtil.doubleArrToDoubleArr(relativeError);

        return new GMResult(arr1, verify, res1, relativeError1, correlationDegree, cvalue);
    }

    //输入是数组
    @Override
    public GMResult GM(double[] data, int t) {
        String[] verify = GMUtil.verify(data); //级比验证结果
        double[] res = GMUtil.doAlgo(data, t); //GM结果
        double[] relativeError = GMUtil.relativeError(data, res); //相对误差结果
        double correlationDegree = GMUtil.correlationDegree(data, res); //均方差比值结果
        double cvalue = GMUtil.smallErrorProbability(data, res); //后验差比值
        //返回数据
        Double[] arr1 = BaseTypeUtil.doubleArrToDoubleArr(data);
        Double[] res1 = BaseTypeUtil.doubleArrToDoubleArr(res);
        Double[] relativeError1 = BaseTypeUtil.doubleArrToDoubleArr(relativeError);

        return new GMResult(arr1, verify, res1, relativeError1, correlationDegree, cvalue);
    }

    //文件输入的Markov模型
    //返回每次迭代的类集合
    @Override
    public MarkovResult Markov(MultipartFile file, int n, int t) throws IOException {
        double[] arr = ExcelHandler.readGMData(file);
        Markov markov = new Markov(arr, n); //第一个预测值
        List<Double[][]> matrices = new ArrayList<>(); //初始各阶的转移概率矩阵集合
        List<Double> values = new ArrayList<>(); //预测值集合
        MarkovResult markovResult = new MarkovResult();
        //附初始值
        markovResult.setData(BaseTypeUtil.doubleArrToDoubleArr(markov.getData()));
        markovResult.setMean(markov.getMean());
        markovResult.setMeanSquare(markov.getMeanSquare());
        markovResult.setLimits(BaseTypeUtil.doubleArrToDoubleArr(markov.getLimits()));
        markovResult.setDataStates(BaseTypeUtil.doubleArrToDoubleArr(markov.getDataStates()));
        markovResult.setVerify(BaseTypeUtil.doubleArrToDoubleArr(markov.doVerify()));
        markovResult.setT(t);
        List<Matrix> matrixList = markov.getMatrices();
        for (Matrix matrix : matrixList) {
            matrices.add(BaseTypeUtil.double2ArrToDouble2Arr(matrix.getArray()));
        }
        markovResult.setMatrices(matrices);
        //迭代获取最终值
        for (int i = 0; i < t; i++) {
            values.add(markov.getValue());
            double value = markov.getValue();
            double[] oldData = markov.getData();
            double[] newData = Arrays.copyOf(oldData, oldData.length + 1);
            newData[newData.length - 1] = value;
            markov.setData(newData);
        }
        markovResult.setValues(values);
        return markovResult;
    }

    @Override
    public MarkovResult Markov(double[] arr, int n, int t) {
        Markov markov = new Markov(arr, n); //第一个预测值
        List<Double[][]> matrices = new ArrayList<>(); //初始各阶的转移概率矩阵集合
        List<Double> values = new ArrayList<>(); //预测值集合
        MarkovResult markovResult = new MarkovResult();
        //附初始值
        markovResult.setData(BaseTypeUtil.doubleArrToDoubleArr(markov.getData()));
        markovResult.setMean(markov.getMean());
        markovResult.setMeanSquare(markov.getMeanSquare());
        markovResult.setLimits(BaseTypeUtil.doubleArrToDoubleArr(markov.getLimits()));
        markovResult.setDataStates(BaseTypeUtil.doubleArrToDoubleArr(markov.getDataStates()));
        markovResult.setVerify(BaseTypeUtil.doubleArrToDoubleArr(markov.doVerify()));
        markovResult.setT(t);
        List<Matrix> matrixList = markov.getMatrices();
        for (Matrix matrix : matrixList) {
            matrices.add(BaseTypeUtil.double2ArrToDouble2Arr(matrix.getArray()));
        }
        markovResult.setMatrices(matrices);
        //迭代获取最终值
        for (int i = 0; i < t; i++) {
            values.add(markov.getValue());
            double value = markov.getValue();
            double[] oldData = markov.getData();
            double[] newData = Arrays.copyOf(oldData, oldData.length + 1);
            newData[newData.length - 1] = value;
            markov.setData(newData);
        }
        markovResult.setValues(values);
        return markovResult;
    }

    @Override
    public void gmArchive(GMArchive gmArchive) {
        gmMapper.gmArchive(gmArchive);
    }

    @Override
    public List<GMArchive> gmListAll() {
        return gmMapper.listAll();
    }

    @Override
    public void gmDelete(String id) {
        gmMapper.deleteById(id);
    }

    @Override
    public void markovArchive(MarkovArchive markovArchive) {
        markovMapper.markovArchive(markovArchive);
    }

    @Override
    public List<MarkovArchive> markovListAll() {
        return markovMapper.listAll();
    }

    @Override
    public void markovDelete(String id) {
        markovMapper.deleteById(id);
    }


}
